package flex.cc.store.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;

import flex.cc.PublicUtil;
import flex.cc.common.utils.CommonUtils;
import flex.cc.config.Config;
import flex.cc.single.dto.entity.VerifyTaskEntity;
import flex.cc.single.service.VerifyTaskService;
import flex.cc.store.dao.StoreActivityConfigDao;
import flex.cc.store.dto.entity.CouponTrackEntity;
import flex.cc.store.dto.entity.StoreActivityConfigEntity;
import flex.cc.store.dto.entity.StoreCouponEntity;
import flex.cc.store.dto.entity.StoreOrderEntity;
import flex.cc.store.dto.entity.StorePackageEntity;
import flex.cc.store.dto.vo.MsgConstant;
import flex.cc.store.service.CouponTrackService;
import flex.cc.store.service.StoreCouponService;
import flex.cc.store.service.StoreOrderService;
import flex.cc.store.service.StorePackageService;
import flex.cc.store.service.StoreQrService;
import flex.cc.store.service.VerifyService;
import flex.cc.store.util.AESSingleUtil;
import flex.cc.store.util.SdSignUtil;
import flex.cc.system.entity.DictCodeEntity;
import flex.cc.system.service.DictCodeService;
import flex.cc.util.APIConfigUtil;
import flex.cc.util.SpecialRuleUtil;

/**
 * 
 * @author WANGCONG
 * 2021年12月16日上午11:09:18
 * @desc 核销确认、通知业务实现层
 */
@Service("verifyService")
@Transactional(rollbackFor = Exception.class)
public class VerifyServiceImpl implements VerifyService{

	private static final Logger logger = LoggerFactory.getLogger(VerifyServiceImpl.class);
	@Resource
	private StoreCouponService couponService;
	@Resource
	private CouponTrackService couponTrackService;
	@Resource
	private StorePackageService packageService;
	@Resource
	private StoreOrderService orderService;
	@Resource
	private StoreQrService qrService;
	@Resource
	private DictCodeService dictCodeService;
    @Autowired
    private StoreActivityConfigDao activityConfigDao;
	@Resource
    private APIConfigUtil apiConfigUtil;
	@Resource
	private VerifyTaskService taskService;
	
	/**
	 * 
	 * @author WANGCONG
	 * 2021年12月16日上午11:19:08
	 * @desc 核销确认验证
	 *  根据卡券的对应服务项目是否勾选 "核销校验车牌"特殊规则  如果勾选校验车牌 否则不校验
	 */
	@SuppressWarnings("serial")
	@Override
	public Map<String, String> verify(String couponNum, String carNo) {
		Map<String, String> resultMap = new HashMap<>();
		//第一步，根据卡券码查询卡券信息，比对卡券绑定的车牌号与传过来的实际车牌号是否一致
		//第二步，判断当前月 ，卡券的服务类型、车牌号是否享受过(只能享受一次)
		StoreCouponEntity couponEntity = couponService.queryByCouponNum(couponNum);
		if(couponEntity!=null){
			String status = couponEntity.getStatus();
			if(!"1".equals(status)){
				resultMap.put("code", "01");
				resultMap.put("msg", "卡券已过期或已使用，请联系平台方");
				saveTrack(couponEntity, "3", "卡券已过期或已使用", "0", "商户扫码");
				return resultMap;
			}
			String real_carNo = couponEntity.getCarNo(); //数据库中存的脱敏车牌号
			String activityId = couponEntity.getActivityId(); //服务类型
			String orderId = couponEntity.getOrderId(); //归属订单id
			
			//服务商
			String provider = couponEntity.getServer();
			//根据orderId获取服务包订单
			StoreOrderEntity storeOrderEntity = orderService.queryByOrderId(orderId);
			//服务包配置编码
			String configCode = storeOrderEntity.getServiceItemCode();
			
			Map<String, Object> reqVo = new HashMap<String, Object>();
			reqVo.put("configCode", configCode);
			reqVo.put("activityCode", activityId);
			reqVo.put("provider", provider);
			List<StoreActivityConfigEntity> activityConfigEntityList = activityConfigDao.queryActivityConfig(reqVo);
			if(activityConfigEntityList.size()>0){
				StoreActivityConfigEntity activityConfigEntity = activityConfigEntityList.get(0);
				//特殊规则
				String specialRules = activityConfigEntity.getSpecialRule();
				if(specialRules.contains("1")){//核销校验车牌
					boolean carb = false;
					if(real_carNo.length()!=carNo.length()){
						carb = true;
					}else{
						for(int i=0; i<real_carNo.length(); i++){
							char c = real_carNo.charAt(i);
							if(c!='*' && c!=carNo.charAt(i)){
								carb = true;
								break;
							}
						}
					}
					if(carb){
						resultMap.put("code", "01");
						resultMap.put("msg", MsgConstant.errorCarNo);
						saveTrack(couponEntity, "3", MsgConstant.errorCarNo, "0", "商户扫码");
						return resultMap;
					}
				}
			}
			
			
//			Map<String,String> params = new HashMap<String,String>(){{
//				put("carNo", carNo);
//				put("activityId", activityId);
//				put("orderId", orderId);
//			}};
//			int count = couponService.findServiceNum(params);
//			if(count>0){
//				resultMap.put("code", "01");
//				resultMap.put("msg", MsgConstant.errorOverNum);
//				saveTrack(couponEntity, "3", MsgConstant.errorOverNum, "0", "商户扫码");
//				return resultMap;
//			}
			resultMap.put("code", "00");
			resultMap.put("msg", "成功");
			Map<String, Object> qr_params = new HashMap<String, Object>();
			qr_params.put("couponNum", couponNum);
			qr_params.put("status", "1"); //是否已核销通过，0-否，1-是
			qrService.updateByParams(qr_params);
			saveTrack(couponEntity, "3", "核销确认成功", "1", "商户扫码");
			return resultMap;
		}else{
			resultMap.put("code", "01");
			resultMap.put("msg", MsgConstant.errorCouponNum);
			StoreCouponEntity entity = new StoreCouponEntity();
			entity.setCouponNum(couponNum);
			entity.setId(999L);
			entity.setStatus("0");
			saveTrack(entity, "3", MsgConstant.errorCouponNum, "0", "商户扫码");
			return resultMap;
		}
		
	}
	
	/**
	 * 
	 * @author WANGCONG
	 * 2021年12月16日下午15:47:06
	 * @desc 核销通知
	 *  1.需判断报文中的卡券码是否核销确认成功，避免商户未核销确认，直接核销通知
	 *  2.调用上游卡券核销接口，将结果返回下游===>V2.0：下游调车服，变更车服状态后再请求上游忽略上游的响应结果
	 */
	@Override
	public Map<String, String> verifyNotice(Map<String, String> postMap) {
		Map<String, String> resultMap = new HashMap<>();
		String couponNum = postMap.get("coupon_num"); //卡券码
		StoreCouponEntity couponEntity = couponService.queryByCouponNum(couponNum);
		String password = "";
		String cardNo = "";
		String sign = "";
		String specificServiceItems = "洗车服务";//服务项目名称
		long hxTime = new Date().getTime();
		if(couponEntity!=null){
			//判断卡券状态
			if(!"1".equals(couponEntity.getStatus())){
				resultMap.put("code", "01");
				resultMap.put("msg", "卡券已过期或已使用，请联系平台方");
				saveTrack(couponEntity, "2", "卡券已过期或已使用", "0", "下游核销通知接口");
				return resultMap;
			}
			//查看卡券码是否核销通过
			Map<String,String> params = new HashMap<String,String>();
			params.put("couponNum", couponNum);
			params.put("result", "1");
			params.put("trackType", "3"); //3-与商户端交互，成功的记录
			int successCount = couponTrackService.findCountByParams(params);
			if(successCount==0){
				resultMap.put("code", "01");
				resultMap.put("msg", "当前卡券还未核销确认");
				saveTrack(couponEntity, "2", "当前卡券还未核销确认", "0", "下游核销通知接口");
				return resultMap;
			}
			StoreOrderEntity orderEntity = orderService.queryByOrderId(couponEntity.getOrderId());
			if(orderEntity==null){
				resultMap.put("code", "01");
				resultMap.put("msg", "卡券码对应订单不存在");
				return resultMap;
			}
			
			//变更卡券核销时间、状态为已使用
			Map<String,Object> coupon_params = new HashMap<String,Object>();
			coupon_params.put("couponNum", couponNum);
			coupon_params.put("status", "3"); //3-已使用（核销完成）
			coupon_params.put("checkDate", new Date());
			coupon_params.put("updateTime", new Date());
			couponService.updateByParam(coupon_params);
			//判断卡券归属服务包状态，变更为已兑现
			String packageCode = couponEntity.getPackageCode();
			StorePackageEntity packageVo = packageService.queryByPackageCode(packageCode);
			if(packageVo!=null && "0".equals(packageVo.getStatus())){
				Map<String,Object> package_params = new HashMap<String,Object>();
				package_params.put("packageCode", packageCode);
				package_params.put("status", "1"); // 1-已兑换
				package_params.put("checkDate", new Date()); //核销时间
				package_params.put("updateTime", new Date());
				packageService.updateByParam(package_params);
			}
			
			resultMap.put("code", "00");
			resultMap.put("msg", "成功");
			
			String serviceItemCode = couponEntity.getActivityId(); //服务类型id
			//根据activityId查flex_dict_code表中对应的项目编码、项目名称
			Map<String, Object> codeParams = new HashMap<String, Object>();
			codeParams.put("code", serviceItemCode);
			codeParams.put("typeCode", "activityName");
			DictCodeEntity codeVo = dictCodeService.getOneByParams(codeParams);
			if(codeVo!=null){
				specificServiceItems = codeVo.getValue();
			}
			String storeUserName = apiConfigUtil.getSYApiConfig("storeUserName");
			String storePassword = apiConfigUtil.getSYApiConfig("storePassword");
			String storeKey = apiConfigUtil.getSYApiConfig("storeKey");
			String storeProTypeCode = apiConfigUtil.getSYApiConfig("storeProTypeCode");
			String storeWriteOffUrl = apiConfigUtil.getSYApiConfig("storeWriteOffUrl");
			try {
				cardNo = couponEntity.getPackageCodeCF();//postMap.get("package_code");
				password = AESSingleUtil.encrypt(storePassword, storeKey);
				StringBuilder sb = new StringBuilder("");
				sb.append(storeUserName).append(password)
				  .append(storeProTypeCode).append(serviceItemCode).append(cardNo)
				  .append("1").append(hxTime);
				sign = SdSignUtil.MD5(sb.toString());
			} catch (Exception e1) {
				saveTrack(couponEntity, "1", "密码加密或数字签名异常", "0", "上游核销接口");
				return resultMap;
			}
	        Map<String, Object> body = new HashMap<String, Object>();
	        body.put("username", storeUserName);
	        body.put("password", password);
	        body.put("proTypeCode", storeProTypeCode);
	        body.put("cardNo", cardNo); //父卡券号
	        body.put("hxStatus", "1");
	        body.put("hxTime", hxTime);
	        body.put("sign", sign);
	        body.put("serviceItemCode", serviceItemCode);
	        body.put("specificServiceItems", specificServiceItems);
	        body.put("jsPrice", ""); //结算价
	        //增加子卡券信息
	        body.put("isChildCoupon", "1"); //是否为子卡券，1-是
	        List<HashMap<String, Object>> childCardList = new ArrayList<HashMap<String, Object>>();
	        HashMap<String, Object> childCard = new HashMap<String, Object>();
	        childCard.put("childCardNo", couponNum); //子卡券号
	        childCard.put("useCount", "1");
	        childCard.put("orderId", couponEntity.getOrderId()); //订单号
	        childCardList.add(childCard);
	        body.put("childCardList", childCardList);
	        
			logger.info("到店类核销通知接口url ==" + storeWriteOffUrl);
			logger.info("到店类核销通知接口请求报文 ==" + CommonUtils.toJSONString(body));
			
	        String resultJson = CommonUtils.storePost(storeWriteOffUrl, CommonUtils.toJSONString(body));
	        //默认成功
//	        String resultJson="{\"result\":{\"errMsg\":\"第三方卡券统一核销接口调用成功！\",\"status\":\"success\"},\"resultCode\":200,\"message\":\"OK\"}";
	        logger.info(couponNum+"到店请求核销接口响应报文-->"+resultJson);
	        
	        String resultCode = "success";  //响应码code
	        if (resultJson != null) {
	        	try {
	        		JSONObject json = JSONObject.parseObject(resultJson);
	        		int code = Integer.valueOf(json.get("resultCode").toString());
	        		if(HttpStatus.SC_OK == code){ //调用成功
	        			JSONObject results = (JSONObject)json.get("result");
	        			String status = results.get("status").toString();
	        			if(status.equals("success")){
	        				//记录卡券轨迹
	        				saveTrack(couponEntity, "1", MsgConstant.successNotice, "1", "上游核销接口");
	        			}else{
	        				resultCode = "error";
	        				String errMsg = results.get("errMsg").toString();
							saveTrack(couponEntity, "1", errMsg, "0", "上游核销接口");
	        			}
	        		}else{
	        			resultCode = "error";
	        			String message = json.get("message").toString();
	        			saveTrack(couponEntity, "1", MsgConstant.errorNotice+":"+message, "0", "上游核销接口");
	        		}
				} catch (Exception e) {
					resultCode = "error";
					saveTrack(couponEntity, "1", MsgConstant.errorResponse, "0", "上游核销接口");
				}
	        }else{
	        	resultCode = "error";
	        	//上游接口响应异常，记录卡券轨迹
	        	saveTrack(couponEntity, "1", MsgConstant.noResponse, "0", "上游核销接口");
	        }
	        //add W 2022年4月2日14:11:22 根据核销结果，操作t_store_verify_task，定时复推上游核销通知任务---start
	        VerifyTaskEntity taskVo = new VerifyTaskEntity();
	        if("success".equals(resultCode)){
	        	taskVo.setCouponNum(couponNum);
	        	taskVo.setStatus(0); //核销结果：0-成功、1-失败
	        	taskVo.setUpdateTime(new Date());
	        	taskService.update(taskVo);
	        }else{
	        	//核销失败，根据卡券码判断t_store_verify_task中是否已存在，若不存在，则插入
	        	Map<String, Object> task_params = new HashMap<String, Object>();
	        	task_params.put("couponNum", couponNum);
	        	VerifyTaskEntity vo = taskService.getOneByParams(task_params);
	        	if(PublicUtil.isEmpty(vo)){
	        		taskVo.setCouponNum(couponNum);
	        		taskVo.setWriteOffUrl(storeWriteOffUrl);
	        		taskVo.setCardType("1");//1-服务包到店、2-服务包代驾、3-单项到店、4-单项代驾、5-健康护理
	        		taskVo.setRequestBody(CommonUtils.toJSONString(body));
	        		taskVo.setResponseBody(resultJson);
	        		taskVo.setStatus(1); //核销结果：0-成功、1-失败
	        		taskVo.setCreateTime(new Date());
	        		taskService.insert(taskVo);
	        	}
	        }
	        //add W 2022年4月2日14:11:22 根据核销结果，操作t_store_verify_task，定时复推上游核销通知任务---end
		}else{
			resultMap.put("code", "01");
			resultMap.put("msg", "卡券不存在");
			return resultMap;
		}
		return resultMap;
	}
	
	/**
	 * 
	 * @author WANGCONG
	 * 2021年12月17日上午9:55:16
	 * @param couponEntity---卡券实体类
	 * @param trackType---轨迹类型：0-车服内部，1-与上游交互，2-与下游交互，3-与商户端交互
	 * @param trackDesc---轨迹描述
	 * @param result---结果：0-失败，1-成功
	 * @param creater---处理人
	 */
	private void saveTrack(StoreCouponEntity couponEntity, String trackType, String trackDesc, String result, String creater){
		Date d = new Date();
        CouponTrackEntity vo = new CouponTrackEntity(couponEntity.getId(),couponEntity.getCouponNum(),
        		trackType,trackDesc,couponEntity.getStatus(),result);
        vo.setIsDelete(0);
		vo.setCreateTime(d);
        vo.setCreater(creater);
        vo.setUpdateTime(d);
        vo.setUpdater(creater);
		couponTrackService.insert(vo);
	}

}
